import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from datetime import datetime, time, timedelta
import time as sys_time

hex_str = "67 c6 69 73 51 ff 4a ec 29 cd ba ab f2 fb e3 46"  #随机秘钥
byte_data = bytes.fromhex(hex_str)
b64_str = base64.b64encode(byte_data).decode()  # Base64 编码
#print(b64_str)  # 输出: 5qfkaw9aZxzK8HnLvYvETA==

# 1. 密钥处理（包含IV）
key_base64 = b64_str
#key_base64 = "Z8Zpc1H/Suwpzbqr8vvjRg=="  # 给定的Base64密钥
key = base64.b64decode(key_base64)  # 解码为16字节（128位）
iv = key  # 初始向量与密钥相同

#解密数据
def aes_decrypt(hex_ciphertext):
    # 将十六进制转字节
    ciphertext = bytes.fromhex(hex_ciphertext)
    # 创建解密器（参数与加密一致）
    cipher = AES.new(key, AES.MODE_CBC, iv)
    # 执行解密
    decrypted_data = cipher.decrypt(ciphertext)
    # 去除填充并转回十六进制
    original_data = unpad(decrypted_data, AES.block_size)
    result=original_data.hex()
    print(result)
    return result

def CP56Time():
    #将当前时间转换为CP56Time2a 格式，并输出十六进制
# 步骤1：获取当前时间（含毫秒）
    current_time = datetime.now()
# 步骤2：分解时间字段
    year = current_time.year - 2000    # CP56Time2a年份从2000开始，取后两位（25）
    month = current_time.month         # 月份（1-12）
    day = current_time.day             # 日（1-31）
    hour = current_time.hour           # 小时（0-23）
    minute = current_time.minute       # 分钟（0-59）
    second = current_time.second       # 秒（0-59）
    millisecond = current_time.microsecond // 1000  # 毫秒（0-999）
# 步骤3：将秒和毫秒合并为总毫秒数（0-59999）
    total_milliseconds = second * 1000 + millisecond
# 步骤4：按CP56Time2a格式构造字节数组
    cp56_bytes = [
    total_milliseconds % 256,      # 低字节（毫秒低位）
    total_milliseconds // 256,     # 高字节（毫秒高位）
    minute,                        # 分钟
    hour,                          # 小时
    day,                           # 日
    month,                         # 月
    year                           # 年（后两位）
]
# 步骤5：转换为字节对象
    cp56_data = bytes(cp56_bytes)
# 步骤6：输出结果（十六进制字符串）
    hex_str = cp56_data.hex().upper()
    #print(f"CP56Time2a字节序列: {hex_str}")  # 示例输出：1F402A0F160519
    #print(hex_str)
    return hex_str

# 定义转换函数
def vin_to_ascii(VIN):
    """
    将VIN码转换为ASCII码字符串，并输出十六进制
    参数: vin (字符串类型，例如"LRW3E7EA5LC025355")
    返回: ASCII码字符串（用空格分隔）
    """
    ascii_list = []  # 存储每个字符的ASCII码
    for char in VIN:
        # 使用ord()函数获取字符的ASCII码值（网页3）
        ascii_value = ord(char)
        hex_str = f"{ascii_value:02X}"
        #hex_list.append(hex_str)
        ascii_list.append(hex_str) # 转换为字符串方便拼接
    # 用空格连接所有ASCII码值（网页7）
    result=" ".join(ascii_list)
    #print(result)
    return result

#小端序十六进制转10进制数
def little_endian_hex_to_dec(hex_str):
    """
    小端序十六进制转十进制
    参数: hex_str (字符串类型，如"78563412"或"78 56 34 12")
    返回: 十进制整数
    """
    # 步骤1：清洗输入（移除空格和前缀）
    clean_hex = hex_str.strip().replace(" ", "").replace("0x", "").upper()

    # 步骤2：分割字节（每两个字符为一组）
    bytes_list = [clean_hex[i:i + 2] for i in range(0, len(clean_hex), 2)]

    # 步骤3：反转字节顺序（小端转大端）
    bytes_list.reverse()

    # 步骤4：拼接为大端序字符串
    big_endian_hex = "".join(bytes_list)
    result=int(big_endian_hex, 16)
    # 步骤5：转换为十进制
    #print(result)
    return result

#十进制转十六进制(包含单字节和2字节）
def decimal_to_hex(decimal_num, num_bytes=0):
    """
    将十进制数转换为十六进制字符串，支持单/双字节输出
    参数:
        decimal_num - 数字类型 (0-65535)
        num_bytes   - 指定输出字节数 (0=自动, 1=单字节, 2=双字节小端序)
    返回: 十六进制字符串（大写）
    """
    # 1. 转换为整数（处理浮点数输入）
    try:
        num_int = int(decimal_num)
    except (TypeError, ValueError):
        raise ValueError("输入必须是数字类型")

    # 2. 自动判断输出格式（根据数值范围）
    if num_bytes == 0:
        num_bytes = 1 if 0 <= num_int <= 255 else 2

    # 3. 验证范围并转换
    if num_bytes == 1:
        if not 0 <= num_int <= 255:
            raise ValueError("单字节模式只支持0-255的整数")
        hex_result = f"{num_int:02X}"  # 2位十六进制[1,5](@ref)

    elif num_bytes == 2:
        if not 0 <= num_int <= 65535:
            raise ValueError("双字节模式只支持0-65535的整数")
        # 转换为小端序双字节格式[1,3,4](@ref)
        hex_result = f"{(num_int & 0xFF):02X}{(num_int >> 8):02X}"

    else:
        raise ValueError("num_bytes参数只能是0,1或2")
    #print(hex_result)
    return hex_result

#十进制数转换为小端序十六进制(多字节）
def decimal_to_little_endian_hex(num, num_bytes=4):
    # 步骤1：将整数转换为小端序字节
    # 确保输入是整数
    if not isinstance(num, int):
        num = int(round(num))  # 四舍五入取整
    byte_data = num.to_bytes(num_bytes, byteorder='little', signed=True)

    # 步骤2：将字节转换为十六进制字符串
    result = byte_data.hex()
    #print(result)
    return result

def update_rates(RATE_MAPPING,RATE_PERIODS):
    for period in RATE_PERIODS:
        rate_key = period["rate_type"]
        # 通过字典映射获取费率（网页1推荐方法）
        rate_config = RATE_MAPPING.get(rate_key, {"energy": 0.0, "service": 0.0})
        period["energy_price"] = rate_config["energy"]
        period["service_fee"] = rate_config["service"]
    result= RATE_PERIODS
    #print(result)
    return result

def find_current_rate(RATE_MAPPING,RATE_PERIODS,current_time: datetime) -> dict:
    """
    匹配当前时间所属的费率时段
    参数: current_time (datetime)
    返回: 费率时段字典
    """
    current = current_time.time()
    updated_periods=update_rates(RATE_MAPPING, RATE_PERIODS)
    for period in updated_periods:
        start = period["start"]
        end = period["end"]

        # 处理跨天时段
        if end < start:
            if (current >= start) or (current < end):
                return period
        elif start <= current < end:
            return period

    raise ValueError(f"未找到时间 {current} 对应的费率时段")

def calculate_cross_interval(RATE_MAPPING, RATE_PERIODS,start_time: datetime, end_time: datetime, total_energy: float) -> list:
    """
    跨时段计费核心逻辑
    """
    current = start_time
    intervals = []
    total_duration = (end_time - start_time).total_seconds()

    while current < end_time:
        period = find_current_rate(RATE_MAPPING,RATE_PERIODS,current)

        # 计算时段结束边界
        period_end_date = current.replace(
            hour=period["end"].hour,
            minute=period["end"].minute,
            second=0,
            microsecond=0
        )
        if period["end"] < period["start"]:  # 跨天处理
            period_end_date += timedelta(days=1)

        interval_end = min(end_time, period_end_date)
        duration = (interval_end - current).total_seconds()
        energy = total_energy * (duration / total_duration)

        energy_price = period["energy_price"]
        service_fee = period["service_fee"]
        if energy_price is None or service_fee is None:
            raise ValueError(f"费率字段未初始化: {period}")

        # 分离计算电费和服务费
        energy_cost = energy * period["energy_price"]
        service_cost = energy * period["service_fee"]
        total_cost = energy_cost + service_cost

        intervals.append({
            "start": current,
            "end": interval_end,
            "rate_type": period["rate_type"],
            "energy": energy,
            "energy_price": period["energy_price"],
            "service_fee": period["service_fee"],
            "energy_cost": energy_cost,
            "service_cost": service_cost,
            "total_cost": total_cost
        })

        current = interval_end

    return intervals


def cost_fee(RATE_MAPPING, RATE_PERIODS, charge_str: str, charge_end_str: str, total_energy: float) -> float:
    """
    计费主入口（增加按费率类型统计金额功能）
    """
    charge_start = datetime.strptime(charge_str, "%Y-%m-%d %H:%M:%S")
    charge_end = datetime.strptime(charge_end_str, "%Y-%m-%d %H:%M:%S")
    result = calculate_cross_interval(RATE_MAPPING, RATE_PERIODS, charge_start, charge_end, total_energy)

    # 初始化统计变量
    total_energy_cost = 0.0
    total_service_cost = 0.0
    rate_energy_sums = {}  # 按费率类型存储电量总和
    rate_energy_cost_sums = {}  # 按费率类型存储电费总和
    rate_service_cost_sums = {}  # 按费率类型存储服务费总和
    rate_total_cost_sums = {}  # 按费率类型存储总费用总和

    # 遍历每个时段计算费用
    for item in result:
        total_energy_cost += item["energy_cost"]
        total_service_cost += item["service_cost"]
        rate_type = item["rate_type"]

        # 按费率类型累加电量
        if rate_type not in rate_energy_sums:
            rate_energy_sums[rate_type] = 0.0
            rate_energy_cost_sums[rate_type] = 0.0
            rate_service_cost_sums[rate_type] = 0.0
            rate_total_cost_sums[rate_type] = 0.0

        rate_energy_sums[rate_type] += item["energy"]
        rate_energy_cost_sums[rate_type] += item["energy_cost"]
        rate_service_cost_sums[rate_type] += item["service_cost"]
        rate_total_cost_sums[rate_type] += item["total_cost"]

        # 打印时段明细
        print(
            f"{item['start'].time()}~{item['end'].time()}".ljust(21),
            f"费率：{item['rate_type']}".ljust(10),
            f"电价：{item['energy_price']}元/度".ljust(15),
            f"服务费：{item['service_fee']}元/度".ljust(15),
            f"电量：{item['energy']:.2f}度".ljust(12),
            f"电费：{item['energy_cost']:.2f}元".ljust(12),
            f"服务费：{item['service_cost']:.2f}元".ljust(12),
            f"合计：{item['total_cost']:.2f}元"
        )
    for rate_type in rate_energy_sums.keys():
        print(
            f"费率类型 {rate_type}: "
            f"总电量={rate_energy_sums[rate_type]:.2f}度, "
            f"电费={rate_energy_cost_sums[rate_type]:.2f}元, "
            f"服务费={rate_service_cost_sums[rate_type]:.2f}元, "
            f"合计={rate_total_cost_sums[rate_type]:.2f}元"
        )
    print(f"总电费：{total_energy_cost:.2f}元")
    print(f"总服务费：{total_service_cost:.2f}元")
    print(f"最终总费用：{total_energy_cost + total_service_cost:.2f}元")
    result=total_energy_cost + total_service_cost
    #print(result)
    return (result,rate_energy_sums,rate_energy_cost_sums,rate_service_cost_sums,rate_total_cost_sums)

# 主程序调用
if __name__ == "__main__":
    CP56Time()
    VIN = "LRW3E7EA5LC025355"  # 示例VIN码
    vin_to_ascii(VIN)
    hex_input = "82 00 00 00"  # 示例输入（小端模式）
    little_endian_hex_to_dec(hex_input)
    encrypted="81969eae35473484ee83476454daebb6016c7a709cefaadee7c67d7ee689ecb26d3fd7b632fa8e2263783e6dfbf2899ed727d1e14abfcbeb2a654c446479a12e9345d39168e5f942f6d9b9f3c77b70eee4b5c6bb88d644aecd8491dd7fc4e155                       "
    aes_decrypt(encrypted)
    RATE_MAPPING = {
        "00": {"energy": 1.5, "service": 2},  # 峰段
        "01": {"energy": 2.0, "service": 1.5},  # 平时段
        "02": {"energy": 1.0, "service": 1.0},  # 离峰时段
        "03": {"energy": 0.8, "service": 0.5}  # 谷段
    }
    RATE_PERIODS = [
        {  # 峰段示例
            "start": time(0, 0),
            "end": time(0, 30),
            "rate_type": "01",
            "energy_price": None,  # 电价部分
            "service_fee": None  # 服务费部分
        },
        {  # 谷段示例
            "start": time(0, 30),
            "end": time(1, 0),
            "rate_type": "02",
            "energy_price": None,  # 电价部分
            "service_fee": None  # 服务费部分
        },
        {  # 跨天时段示例
            "start": time(1, 0),
            "end": time(0, 0),
            "rate_type": "03",
            "energy_price": None,  # 电价部分
            "service_fee": None  # 服务费部分
        }
    ]
    update_rates(RATE_MAPPING, RATE_PERIODS)
    cost_fee(RATE_MAPPING,RATE_PERIODS,"2025-05-28 00:25:00", "2025-05-28 00:40:00", 10)
    test_num = 0 # 十进制数
    decimal_to_little_endian_hex(test_num,5)
    num = 0  # 浮点数输入
    decimal_to_hex(num,2)  # 调用函数